package com.yujie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yujie.domain.Dictionary;
import com.yujie.domain.DictionaryCommon;
import com.yujie.domain.Employee;
import com.yujie.domain.dto.EmployeeDTO;
import com.yujie.domain.query.EmployeeQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yujie.exception.BusinessException;
import com.yujie.exception.EmployeeErrorCodeEnum;
import com.yujie.mapper.DictionaryMapper;
import com.yujie.mapper.EmployeeMapper;
import com.yujie.service.DictionaryCommonService;
import com.yujie.service.DictionaryService;
import com.yujie.service.EmployeeService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.sql.SQLIntegrityConstraintViolationException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


/**
 * (Employee)表服务实现类
 *
 * @author wangyujie
 * @since 2023-08-14 20:12:24
 */
@Service("employeeService")
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {
    @Resource
    private EmployeeMapper employeeMapper;
    @Resource
    private DictionaryMapper dictionaryMapper;
    @Resource
    private DictionaryService dictionaryService;
    @Resource
    private DictionaryCommonService dictionaryCommonService;
    @Value("${file.template.path}")
    private String templatePath;
    @Override
    public boolean saveEmployee(EmployeeQuery query){
        Employee employee = new Employee();
        BeanUtils.copyProperties(query,employee);
        long id = IdWorker.getId();
        employee.setType(id);
        try {
            save(employee);
        }catch (Exception e){
            if(e.getCause() instanceof SQLIntegrityConstraintViolationException){
                throw new BusinessException("员工编号冲突："+employee.getNo(), EmployeeErrorCodeEnum.USER_ERROR_0002);
            }else{
                throw e;
            }
        }
        for (Dictionary type : query.getTypes()) {
            DictionaryCommon dictionaryCommon = new DictionaryCommon();
            dictionaryCommon.setDictionaryId(type.getId());
            dictionaryCommon.setForeignKeyId(id);
            dictionaryCommon.setRemark(type.getRemark());
            dictionaryCommonService.save(dictionaryCommon);
        }
        return true;
    }

    public boolean updateEmployee(EmployeeQuery query){
        Employee employee = new Employee();
        BeanUtils.copyProperties(query,employee);
        updateById(employee);


        DictionaryCommon d = new DictionaryCommon();
        d.setForeignKeyId(employee.getType());
        QueryWrapper<DictionaryCommon> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(d);
        List<DictionaryCommon> dictionaryCommonList = dictionaryCommonService.list(queryWrapper);
        //删除该用户所有类型
        for (DictionaryCommon dictionaryCommon : dictionaryCommonList) {
            dictionaryCommonService.removeById(dictionaryCommon.getId());
        }
        //添加新的用户类型
        for (Dictionary type : query.getTypes()) {
            DictionaryCommon dictionaryCommon = new DictionaryCommon();
            dictionaryCommon.setDictionaryId(type.getId());
            dictionaryCommon.setForeignKeyId(employee.getType());
            dictionaryCommon.setRemark(type.getRemark());
            dictionaryCommonService.save(dictionaryCommon);
        }
        return true;
    }

    @Override
    public Page<EmployeeDTO> listPage(Page page, EmployeeQuery query) {
        Page<EmployeeDTO> employeeDTOPage = employeeMapper.listPage(page, query);
        return employeeDTOPage;
    }


    @Transactional
    @Override
    public String importEmployeeFromExcel(MultipartFile file) throws Exception {
        Workbook workbook = WorkbookFactory.create(file.getInputStream());
        int count = 0 ;
        List<Employee> listEmp = new ArrayList();
        // 遍历第一个工作表的每一行
        for (Row row : workbook.getSheetAt(0)) {
            // 跳过第一行
            if(count == 0){
                count++;
                continue;
            }
            Employee employee = new Employee();
            Employee emp = excelORM(row, employee);
            if(emp != null){
                listEmp.add(emp);
            }
        }

        for (Employee emp : listEmp) {
            String no = emp.getNo();
            try {
                save(emp);
            }catch (Exception e){
                if(e.getCause() instanceof SQLIntegrityConstraintViolationException){
                    throw new BusinessException("员工编号冲突："+no,EmployeeErrorCodeEnum.USER_ERROR_0002);
                }else{
                    throw e;
                }
            }
        }
        return null;
    }

    @Override
    public void exportEmpExcel(Page page,EmployeeQuery query) {
        Page<EmployeeDTO> empList= null;
        if(query.getSwitchValue()){
            page.setSize(Integer.MAX_VALUE);
            empList = listPage(page,query);
        }else{
            empList = listPage(page,query);
        }
        writeExcel(empList);
    }

    @Override
    public void exportTemplateExcel() throws Exception {
        // 读取文件内容
        File file = new File(templatePath+"员工登记信息模板.xlsx");
        if (!file.exists()) {
            File parent = file.getParentFile();
            if (!parent.exists()) {
                parent.mkdirs();
            }
        }
        try(FileInputStream inputStream = new FileInputStream(file);
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
                byte[] buffer = new byte[1024]; // 缓冲区大小
                int bytesRead;
                // 将文件内容写入输出流
                HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("员工登记信息模板.xlsx", "UTF-8"));
                while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
                    // 将读取的数据写入输出流
                    response.getOutputStream().write(buffer, 0, bytesRead);
                }
            response.getOutputStream().flush();
        }
    }

    private void writeExcel(Page<EmployeeDTO> page){
        List<EmployeeDTO> employeeList = page.getRecords();
        //查询性别字典 转map 0:女
        List<Dictionary> listSexType = dictionaryMapper.listByCode("Sex");
        Map<String, String> mapSexType = listSexType.stream()
                .collect(Collectors.toMap(Dictionary::getValue, Dictionary::getName));

        try (FileInputStream templateInputStream = new FileInputStream(templatePath+"员工登记信息模板.xlsx");
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

            Workbook workbook = new XSSFWorkbook(templateInputStream);
            templateInputStream.close();
            Sheet sheet = workbook.getSheetAt(0);
            for (int i = 0; i < employeeList.size(); i++) {
                Row row = sheet.createRow(i + 1);
                row.createCell(0).setCellValue(employeeList.get(i).getName());
                row.createCell(1).setCellValue(employeeList.get(i).getNo());
                row.createCell(2).setCellValue(mapSexType.get(employeeList.get(i).getSex().toString()));
                row.createCell(3).setCellValue(employeeList.get(i).getAge());
                row.createCell(4).setCellValue(employeeList.get(i).getPhone());
                row.createCell(5).setCellValue(employeeList.get(i).getEmail());

                ArrayList<Dictionary> types = employeeList.get(i).getTypes();
                StringBuilder result = new StringBuilder();
                for (Dictionary type : types) {
                    result.append(type.getName()+",");
                }
                // 去除末尾的逗号
                if (result.length() > 0) {
                    result.deleteCharAt(result.length() - 1);
                }
                row.createCell(6).setCellValue(result.toString());

                CellStyle style = workbook.createCellStyle();
                style.setDataFormat(workbook.getCreationHelper().createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
                // 设置时间格式
                Cell createTimeCell = row.createCell(7);
                createTimeCell.setCellValue(employeeList.get(i).getCreateTime());
                createTimeCell.setCellStyle(style);

            }
            workbook.write(outputStream);
            // 发送 Excel 文件给客户端下载
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            //response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("员工登记信息.xlsx", "UTF-8"));
            response.getOutputStream().write(outputStream.toByteArray());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    private Employee excelORM(Row row, Employee employee){
        boolean emptyRow = true;
        for (Cell cell : row) {
            if (isCellNull(cell)) {
                // 只要有一个单元格有数据，就不是空行
                emptyRow = false;
                break;
            }
        }
        // 该行单元格全部是空就跳过
        if (emptyRow) {
            return null;
        }

        // 处理第 1 列数据
        Cell cell = row.getCell(0);
        if (isCellNull(cell)) {
            String name = cell.getStringCellValue();
            employee.setName(name);
        }else{
            throw new BusinessException("员工姓名不能为空",EmployeeErrorCodeEnum.USER_ERROR_0002);
        }
        cell = row.getCell(1);
        if (isCellNull(cell)) {
            cell.setCellType(Cell.CELL_TYPE_STRING);
            String no = cell.getStringCellValue();
            employee.setNo(no);
        }else{
            throw new BusinessException("员工编号不能为空",EmployeeErrorCodeEnum.USER_ERROR_0002);
        }
        cell = row.getCell(2);
        if (isCellNull(cell)) {
            String sex = cell.getStringCellValue();
            //查询性别字典 转map 女:0
            List<Dictionary> listSexType = dictionaryMapper.listByCode("Sex");
            Map<String, String> mapSexType = listSexType.stream()
                    .collect(Collectors.toMap( Dictionary::getName,Dictionary::getValue));
            employee.setSex(Integer.parseInt(mapSexType.get(sex)));
        }else{
            throw new BusinessException("员工性别不能为空",EmployeeErrorCodeEnum.USER_ERROR_0002);
        }

        cell = row.getCell(3);
        if (isCellNull(cell)) {
            int age = (int) cell.getNumericCellValue();
            employee.setAge(age);
        }else{
            throw new BusinessException("员工年龄不能为空",EmployeeErrorCodeEnum.USER_ERROR_0002);
        }
        cell = row.getCell(4);
        if (isCellNull(cell)) {
            cell.setCellType(Cell.CELL_TYPE_STRING);
            String phone = cell.getStringCellValue();
            employee.setPhone(phone);
        }

        cell = row.getCell(5);
        if (isCellNull(cell)) {
            String email = cell.getStringCellValue();
            employee.setEmail(email);
        }
        employee.setType(IdWorker.getId());
        cell = row.getCell(6);
        if (isCellNull(cell)) {
            if(cell.getStringCellValue().contains("，")){
                throw new BusinessException("员工类型请使用英文逗号分隔",EmployeeErrorCodeEnum.USER_ERROR_0002);
            }
            String[] types = cell.getStringCellValue().split(",");
            List<Dictionary> listEmployeeType = dictionaryMapper.listByCode("Employee");
            for (String type : types) {
                for (Dictionary dictionary : listEmployeeType) {
                    if(type.equals(dictionary.getName())){
                        DictionaryCommon dictionaryCommon = new DictionaryCommon();
                        dictionaryCommon.setDictionaryId(dictionary.getId());
                        dictionaryCommon.setForeignKeyId(employee.getType());
                        dictionaryCommon.setRemark(dictionary.getRemark());
                        dictionaryCommonService.save(dictionaryCommon);
                    }
                }
            }

        }else{
            throw new BusinessException("员工类型不能为空",EmployeeErrorCodeEnum.USER_ERROR_0002);
        }
        cell = row.getCell(7);
        if (isCellNull(cell)) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date createTimeDate = cell.getDateCellValue();
            String createTimeStr = dateFormat.format(createTimeDate);
            Date createTime = null;
            try {
                createTime = dateFormat.parse(createTimeStr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            employee.setCreateTime(createTime);
        }else{
            throw new BusinessException("登记时间不能为空", EmployeeErrorCodeEnum.USER_ERROR_0002);
        }
        return employee;
    }

    /**
     *
     * @param cell
     * @return true 非空 false 空
     */
    private boolean isCellNull(Cell cell){
        if (cell != null   && cell.getCellType() != Cell.CELL_TYPE_BLANK) {
            return true;
        }
        return false;
    }

}

